<template>
  <div>
    <el-row>
      <el-col :span="24">
        <el-card class="box-card">
          <el-row>
            <el-col :span="4" style="padding: 10px 20px;">
              <el-progress :stroke-width="26" :percentage="loadAverages1MinPct" :format="progressRenderTextLoadAverages1Min"></el-progress>
              <el-progress :stroke-width="26" :percentage="loadAverages5MinPct" :format="progressRenderTextLoadAverages5Min" style="margin-top:10px"></el-progress>
              <el-progress :stroke-width="26" :percentage="loadAverages15MinPct" :format="progressRenderTextLoadAverages15Min" style="margin-top:10px"></el-progress>
            </el-col>
            <el-col :span="4">
              <el-progress type="dashboard" :percentage="cpuUsage" :format="progressRenderTextCPUUsage"></el-progress>
            </el-col>
            <el-col :span="4">
              <el-progress type="dashboard" :percentage="memoryUsagePct" :format="progressRenderTextMemoryUsage"></el-progress>
            </el-col>
            <el-col :span="4">
              <el-progress type="dashboard" :percentage="swapUsagePct" :format="progressRenderTextSwapUsage"></el-progress>
            </el-col>
            <el-col :span="4">
              <el-progress type="dashboard" :percentage="rootDiskUsage" :format="progressRenderTextDiskUsage"></el-progress>
            </el-col>
            <el-col :span="4">
              <div id="sys-time">{{time}}</div>
            </el-col>
          </el-row>
        </el-card>
      </el-col>
      <el-col :span="12" style="margin-top:10px;padding-right:5px;">
        <el-card class="box-card">
          <div slot="header" class="clearfix">
            <span>进程</span>
          </div>
          <el-table :data="processes" max-height="300" :show-header="false">
            <el-table-column width="80" prop="pid"></el-table-column>
            <el-table-column prop="command"></el-table-column>
          </el-table>
        </el-card>
      </el-col>
      <el-col :span="12" style="margin-top:10px;padding-left:5px;">
        <el-card class="box-card">
          <div slot="header" class="clearfix">
            <span>存储</span>
          </div>
          <el-table :data="diskUsage" max-height="300" :show-header="false">
            <el-table-column prop="mounted"></el-table-column>
            <el-table-column prop="avail"></el-table-column>
            <el-table-column>
              <template slot-scope="scope">
                <el-progress :text-inside="true" :stroke-width="26" :percentage="parseInt(scope.row.use)"></el-progress>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script>
import Chart from 'chart.js';
export default {
    data() {
        return {
            loadAverages1Min : 0,
            loadAverages5Min : 0,
            loadAverages15Min : 0,
            cpuUsage : 30,
            memoryTotal : 1,
            memoryUsed : 0,
            swapTotal:1,
            swapUsed:0,
            rootDiskUsage : 0,
            time : null,
            refreshTimer : null,
            processes : [],
            diskUsage : [],
        };
    },
    computed : {
        loadAverages1MinPct() { 
            let value = parseInt(this.loadAverages1Min / 1 * 100);
            return value > 100 ? 100 : value;
        },
        loadAverages5MinPct() { 
            let value = parseInt(this.loadAverages5Min / 1 * 100); 
            return value > 100 ? 100 : value;
        },
        loadAverages15MinPct() { 
            let value = parseInt(this.loadAverages15Min / 1 * 100); 
            return value > 100 ? 100 : value;
        },
        memoryUsagePct() {
            let value = parseFloat((this.memoryUsed / this.memoryTotal).toFixed(2));
            return value > 100 ? 100 : value;
        },
        swapUsagePct() {
            let value = parseFloat((this.swapUsed / this.swapTotal).toFixed(2));
            return value > 100 ? 100 : value;
        },
    },
    async mounted() {
        await this.refresh();
    },
    destroyed () {
        if ( null != this.refreshTimer ) {
            clearTimeout(this.refreshTimer);
        }
    },
    methods : {
        /** 刷新数据 */
        async refresh() {
            console.log( (new Date()) + ' Dashboard.refresh');

            let server = this.$store.getters.serverCurrent;
            let client = await server.getSshClient();
            let top = await client.exec('top -b -n 1');
            top = top.split('\r\n');
            
            let sysRegex = new RegExp(`^top - (?<time>\\d+:\\d+:\\d+) up\\s+(?<duration>.*?),\\s+(?<users>\\d+) users,\\s+load average: (?<load1>[\\d\\.]+), (?<load5>[\\d\\.]+), (?<load15>[\\d\\.]+)$`, '');
            let line1Match = top[0].match(sysRegex);
            this.loadAverages1Min = line1Match.groups.load1;
            this.loadAverages5Min = line1Match.groups.load5;
            this.loadAverages15Min = line1Match.groups.load15;
            this.time = line1Match.groups.time;

            let procStat = await client.exec('cat /proc/stat');
            procStat = procStat.split('\r\n');
            let cpuUsage = procStat[0].split(' ');
            cpuUsage = (cpuUsage[2]*1+cpuUsage[4]*1) * 100 / (cpuUsage[2]*1+cpuUsage[4]*1+cpuUsage[5]*1);
            this.cpuUsage = cpuUsage.toFixed(2)*1;

            let free = await client.exec('free');
            let memRegex = /Mem:\s+(?<total>\d+)\s+(?<used>\d+)\s+(?<free>\d+)\s+(?<shared>\d+)\s+(?<buff>\d+)\s+(?<available>\d+)/;
            let memMatch = free.match(memRegex);
            this.memoryTotal = memMatch.groups.total;
            this.memoryUsed = memMatch.groups.used;
            let swapRegex = /Swap:\s+(?<total>\d+)\s+(?<used>\d+)\s+(?<free>\d+)/;
            let swapMatch = free.match(swapRegex);
            this.swapTotal = 0 == swapMatch.groups.total ? 1 : swapMatch.groups.total;
            this.swapUsed = swapMatch.groups.used;

            let df = await client.exec('df -h');
            df = df.trim().split('\r\n');
            df.shift();
            let dfRegex = /^(?<fs>\S+)\s+(?<size>\S+)\s+(?<used>\S+)\s+(?<avail>\S+)\s+(?<use>\S+)%\s+(?<mounted>.+)$/;
            this.diskUsage = [];
            for ( let i=0; i<df.length; i++ ) {
                let dfMatch = df[i].match(dfRegex);
                this.diskUsage.push(dfMatch.groups);
                if ( '/' == dfMatch.groups.mounted ) {
                    this.rootDiskUsage = parseInt(dfMatch.groups.use);
                }
            }

            let ps = await client.exec('ps -auxwww');
            ps = ps.trim().split('\r\n');
            ps.shift();
            let psRegex = /^(?<user>\S+)\s+(?<pid>\d+)\s+(?<cpu>[\d.]+)\s+(?<mem>[\d.]+)\s+(?<vsz>[\d.]+)\s+(?<rss>[\d.]+)\s+(?<tty>\S+)\s+(?<stat>\S+)\s+(?<start>\S+)\s+(?<time>\S+)\s+(?<command>.*)/;
            this.processes = [];
            for ( let i=0; i<ps.length; i++ ) {
                let psMatch = ps[i].match(psRegex);
                this.processes.push(psMatch.groups);
            }

            let $this = this;
            this.refreshTimer = setTimeout(function() { $this.refresh(); }, 5000);
        },

        /** */
        progressRenderTextLoadAverages1Min() { return this.loadAverages1Min; },
        /** */
        progressRenderTextLoadAverages5Min() { return this.loadAverages5Min; },
        /** */
        progressRenderTextLoadAverages15Min() { return this.loadAverages15Min; },
        /** */
        progressRenderTextCPUUsage() { return `CPU : ${this.cpuUsage}%`; },
        /** */
        progressRenderTextMemoryUsage( percentage ) { return `内存 : ${percentage}%`; },
        /** */
        progressRenderTextSwapUsage( percentage ) { return `Swap : ${percentage}%`; },
        /** */
        progressRenderTextDiskUsage( percentage ) { return `存储 : ${percentage}%`; },
    },
}
</script>
<style scoped>
#sys-time {border: solid 6px #e5e9f2;width: 120px;height: 120px;line-height: 120px;text-align: center;font-size: 1.3em;border-radius: 50%;}
</style>